package com.ken.mall.comm;

import com.ken.mall.exception.NeedLoginException;
import com.ken.mall.exception.NoAclException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Set;

/**
 * controller 增强器
 * 全局异常处理
 *
 * @author ken
 * @since 2018/05/14
 */
@ControllerAdvice
@Slf4j
public class CommonExceptionAdvice {

    private ObjectError error;

    /**
     * 未捕获异常
     *
     * @param request
     * @param ex
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public ServerResponse defaultExceptionHandler(HttpServletRequest request, Exception ex) {
        StringBuffer url = request.getRequestURL();
        log.error("系统错误，请求URL" + url.toString() + "错误：", ex);
        return ServerResponse.createByErrorMessage("系统错误，请重试或联系管理员");
    }

    /**
     * 请求模式错误
     *
     * @param ex
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
    public ServerResponse requestMethodExceptionHandler(HttpRequestMethodNotSupportedException ex) {
        return ServerResponse.createByErrorMessage(ex.getLocalizedMessage());
    }

    @ResponseBody
    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    public ServerResponse missingRequestParameterExceptionHandler(MissingServletRequestParameterException ex) {
        return ServerResponse.createByErrorMessage(ex.getLocalizedMessage());
    }

    /**
     * 方法级别参数校验全局处理
     *
     * @param ex
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = ConstraintViolationException.class)
    public ServerResponse constraintViolationException(ConstraintViolationException ex) {
        Set<ConstraintViolation<?>> violations = ex.getConstraintViolations();
        StringBuffer message = new StringBuffer();
        for (ConstraintViolation<?> item : violations) {
            message.append(item.getMessage());
            message.append("\n");
        }
        return ServerResponse.createByErrorMessage(message.toString());
    }

    /**
     * model级别参数校验全局处理
     *
     * @param ex
     * @return
     */
    @ResponseBody
    @ExceptionHandler(value = BindException.class)
    public ServerResponse constraintViolationException(BindException ex) {
        BindingResult result = ex.getBindingResult();
        String message = null;
        if (result.hasErrors()) {
            List<ObjectError> allErrors = result.getAllErrors();
            StringBuffer sb = new StringBuffer();
            for (ObjectError error : allErrors) {
                sb.append(error.getDefaultMessage());
                sb.append("\n");
            }
            message = sb.toString();
        }
        return ServerResponse.createByErrorMessage(message);
    }

    /**
     * 登录拦截同一返回
     * @param ex 自定义未登录异常
     */
    @ResponseBody
    @ExceptionHandler(value = NeedLoginException.class)
    public ServerResponse needLoginExceptionHandler(NeedLoginException ex) {
        return ServerResponse.createByErrorCodeMessage(ResponseCode.NEED_LOGIN.getCode(), StringUtils.isNotBlank(ex.getMessage()) ? ex.getMessage() : ResponseCode.NEED_LOGIN.getDesc());
    }

    /**
     * 权限拦截同一返回
     * @param ex 自定义无权限异常
     */
    @ResponseBody
    @ExceptionHandler(value = NoAclException.class)
    public ServerResponse noAclExceptionHandler(NoAclException ex) {
        return ServerResponse.createByErrorCodeMessage(ResponseCode.NO_ACL.getCode(), StringUtils.isNotBlank(ex.getMessage()) ? ex.getMessage() : ResponseCode.NO_ACL.getDesc());
    }
}
